#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>		/* signal */

#include "a311d-setenv.h"

/**
******************************************************************************
* @file           : a311d-setenv.c
* @brief          : implement for a311d-setenv.c file.
*                   This file contains the common implement of the application.
* @author			: ac
* @attention
*
*		Copyright (c) 2021 Technology Co., Ltd.
*
*******************************************************************************
*/

/*
 * globla variable
 */



/*
 * function declaration
 */
void __do_abnormal(const char * str);


/**
 * create_partition_file - create partition temp file.
 * @none
 */
static int create_partition_file(void)
{
    char buff[128] = {0};
    int ret = 0xac;

    sprintf(buff, "dd if=%s of=%s bs=1k count=64 > /dev/null", 
            PARTITION_NUM, 
            DEVINFO);
    ret = system(buff);

    return ret == 0 ? 0 : -1;
}

/**
 * open_partition_file - open partition temp file.
 * @file_name - file name
 */
static FILE * open_partition_file(char * file_name)
{
    FILE * fp = NULL;

    fp = fopen(file_name, "r");
    if (fp == NULL) {
        printf("error : fopen [%s] file fail...\n", file_name);
        __do_abnormal(__FUNCTION__);
    }

    return fp;
}

/**
 * close_partition_file - close partition temp file.
 *  @fp	: file handler pointer
 */
static void close_partition_file( FILE * fp)
{
    if (fp != NULL) {
        fclose(fp);
    }
}

/**
 * get_file_content - get file content.
 *  @fp	: file handler pointer
 *	@buff : content buffer 
 *	@len  : buffer length
 */
static int get_file_content(FILE * fp, unsigned char * buff, int len)
{
    int ret = 0xac;

    assert(fp != NULL);

    ret = fread(buff, 1, len, fp);
    if (ret <= 0) {
        printf("error : fread file fail.\n");
        __do_abnormal(__FUNCTION__);
    }
	printf("ret = %d\n", ret);

    return 0;
}

/**
 * get_parameter - get related parameters.
 *	@buff : content buffer 
 *	@sn	: sn
 *	@area : area 
 *	@series	: series number
 *	@model : model
 */
static int get_parameter(unsigned char * buff, 
                         char * sn, 
                         unsigned char * area,
                         unsigned short * series, 
                         unsigned short * model)
{
    assert(buff != NULL);
	
	#if 0
	int i;
	printf("ac start:\n");
	for (i = 0; i < 1024; i++)
		printf("0x%x ", buff[i]);
	printf("ac end\n");
       

    /* sn */
    memcpy(sn, buff + 0x88, 12);
    if (strlen(sn) != 12) {
        printf("sn error.\n");
        __do_abnormal(__FUNCTION__);
    }
    #endif

    /* series and model */
    memcpy(series, buff + 0x5a, 2);		/* series */
    memcpy(model, buff + 0x58, 2);		/* model */
    // printf("series = 0x%02x, model = 0x%02x\n", *series, *model);

    /* area */
    memcpy(area, buff + 0x30, 1);
    if (*area > 6) {
        printf("area code [%d] error.\n", *area);
        __do_abnormal(__FUNCTION__);
    } 

    return 0;
}

/**
 * paremeter_operation - get parameters; for upper layer call.
 *	@sn	: sn
 *	@area : area 
 *	@series	: series number
 *	@model : model
 */
int paremeter_operation(char * sn, 
                        unsigned char * area,
                        unsigned short * series, 
                        unsigned short * model)
{
    FILE * fp = NULL;
    unsigned char buff[1024] = {0};

    if ( 0 != create_partition_file())
        __do_abnormal(__FUNCTION__);

    /* open file */
    fp = open_partition_file(DEVINFO); 

    /* get file content */
    get_file_content(fp, buff, 1024);

    /* get parameter */
    get_parameter(buff, sn, area, series, model);

    /* close file */
    close_partition_file(fp);

    return 0;
}

/**
 * __do_abnormal - exception handling.
 *	@str - function name
 */
void __do_abnormal(const char * str)
{
    printf("%s abnormal, program terminated...\n", str);
    exit(0);
}

